/*
 * PublicLog.cpp
 *
 *  Created on: 2015-6-24
 *      Author: root
 */
#include"PublicLog.h"
#include"PublicTool.h"
#include"PublicThread.h"

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdarg.h>
#include<dirent.h>
#ifdef USE_CMD_COLOR
#include<windows.h>
#define FATAL_COLOR		0x06
#define ERROR_COLOR		0x0C
#define WARNING_COLOR	0x0E
#define INFO_COLOR		0x0B
#define DEBUG_COLOR		0x07
#define FINE_COLOR		0x07
#define FINEST_COLOR	0x07
//FOREGROUND_INTENSITY|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED
#define NORMAL_COLOR	0x0F
static int colortype[]={
FATAL_COLOR,ERROR_COLOR,WARNING_COLOR,INFO_COLOR,
DEBUG_COLOR,FINE_COLOR,FINEST_COLOR,NORMAL_COLOR};
static HANDLE nStdHandle=GetStdHandle(STD_OUTPUT_HANDLE);
#else
#define FATAL_COLOR		"\033[01;31m"
#define ERROR_COLOR		"\033[22;31m"
#define WARNING_COLOR	"\033[01;33m"
#define INFO_COLOR		"\033[22;36m"
#define DEBUG_COLOR		"\033[01;37m"
#define FINE_COLOR		"\033[22;37m"
#define FINEST_COLOR	"\033[22;37m"
#define NORMAL_COLOR	"\033[0m"
static const char*colortype[]={
FATAL_COLOR,ERROR_COLOR,WARNING_COLOR,INFO_COLOR,
DEBUG_COLOR,FINE_COLOR,FINEST_COLOR,NORMAL_COLOR};
#endif
#define MAX_BUFFSIZE 20480
#define SEEK_DATETIME -604800
#define SAFE_CLOSE(x) do{if(x)fclose(x);x=NULL;}while(0)
class PublicLog{
FILE*normal_fp;//普通文件指针
FILE*error_fp;//错误文件指针
FILE*ex_fp;//扩展信息文件指针
int  today;//当前日期
char PerFileName[128];//文件名前缀
int  bInitFile;//初始化文件
public:
PublicLog(){
	normal_fp=NULL;
	error_fp=NULL;
	ex_fp=NULL;
	today=0;
	memset(PerFileName,0,sizeof(PerFileName));
	bInitFile=0;
}
~PublicLog(){
	ClosePublicLog();
}
static int  DebugMode;
static int  ShowMode;
void WriteLog(int level,const char*DateTime,const char*Data){
	if(bInitFile==0)return;
	CheckFile();
	char Buffer[MAX_BUFFSIZE]={0};
	int Size=snprintf(Buffer,MAX_BUFFSIZE,"[%s]%s\n",DateTime,Data);
	if(level==_ERROR_){
		fwrite(Buffer,1,Size,error_fp);
	}else
	if(level==_FINE_){
		fwrite(Buffer,1,Size,ex_fp);
	}else{
		fwrite(Buffer,1,Size,normal_fp);
	}
}
private:
FILE*OpenLog(const char*datestr,const char*flag){
	FILE*fp=NULL;
	char FullFileName[128]={0};
	sprintf(FullFileName,"%s_%s.%s.log",PerFileName,datestr,flag);
	fp=fopen(FullFileName,"ab");
	if(fp!=NULL)setbuf(fp,0);
	return fp;
}
//打开日志
void OpenLog(){
	char DateString[32]={0};
	GetDateString(DateString,sizeof(DateString));
	normal_fp=OpenLog(DateString,"nor");
	error_fp=OpenLog(DateString,"err");
	ex_fp=OpenLog(DateString,"ex");
	today=GetToDay();
}
void CloseLog(){
	SAFE_CLOSE(normal_fp);
	SAFE_CLOSE(error_fp);
	SAFE_CLOSE(ex_fp);
}
//删除日志
void DelLog(){
	char CheckDateString[32]={0};
	char CheckFileName[128]={0};
	char CheckFileNameRule[128]={0};
	sprintf(CheckFileName,"%s_",PerFileName);//文件名前缀
	sprintf(CheckFileNameRule,"%s_%%[^._]",PerFileName);//检查规则
	GetDateString(CheckDateString,sizeof(CheckDateString),SEEK_DATETIME);//检查日期
	DIR *dir = opendir(".");
	struct dirent *dirp = NULL;
	if(dir!=NULL){
		while((dirp = readdir(dir))!=NULL){
			//排除非文件类型
#ifndef __MINGW32__                    
			if(dirp->d_type!=8)
				continue;
#endif                        
			//排除前缀不一致的
			if(strncmp(dirp->d_name,CheckFileName,strlen(CheckFileName))!=0)
				continue;
			char DateString[32]={0};
			//根据规则获取时间
			sscanf(dirp->d_name,CheckFileNameRule,DateString);
			if(strlen(CheckDateString)==strlen(DateString)){
				if(strcmp(CheckDateString,DateString)>0){
					unlink(dirp->d_name);
				}
			}
		}
		closedir(dir);
	}
}
void CheckFile(){
	if(today!=GetToDay()){
		CloseLog();
		DelLog();
		OpenLog();
	}
}
public:
int OpenPublicLog(const char*perfilename){
	strcpy(PerFileName,perfilename);
	bInitFile=1;
	CheckFile();
	return 0;
}
int ClosePublicLog(){
	if(bInitFile==0)
		return 0;
	bInitFile=0;
	sleep(1);
	CloseLog();
	return 0;
}
};
int  PublicLog::DebugMode=0;
int  PublicLog::ShowMode=1;	
#if USE_PUBLIC_LOG_EX
PublicLock mutex;
PublicLog g_PublicLog;
void SetEnableDebug(int bDebug){
    PublicLog::DebugMode=bDebug;
}
void SetDisableShow(int disShow){
	if(disShow){
		PublicLog::ShowMode=0;
	}else{
		PublicLog::ShowMode=1;
	}
}
void Log(int level,const char*format,...){
//非debug模式不显示信息
    if(PublicLog::DebugMode==0&&level==_DEBUG_) return;
    mutex.Lock();
    char DateTimeString[32]={0};
    char Buffer[MAX_BUFFSIZE]={0};
    int Size=0;
    va_list arguments;
    va_start(arguments,format);
    Size=vsnprintf(Buffer,MAX_BUFFSIZE-64,format,arguments);
    va_end(arguments);
    if(Size>0){
		GetDateTimeString(DateTimeString,sizeof(DateTimeString));
		if(PublicLog::ShowMode){
#ifdef USE_CMD_COLOR
			SetConsoleTextAttribute(nStdHandle,colortype[level]);
			printf("[%s]%s\n",DateTimeString,Buffer);
			SetConsoleTextAttribute(nStdHandle,colortype[_NORMAL_]);
#else			
			printf("%s[%s]%s%s\n",colortype[level],DateTimeString,Buffer,colortype[_NORMAL_]);
#endif			
		}
		g_PublicLog.WriteLog(level,DateTimeString,Buffer);
    }
    mutex.UnLock();
}
//打开日志文件
int OpenPublicLog(const char*perfilename){
	g_PublicLog.OpenPublicLog(perfilename);
	INFO("******日志创建成功******");
	return 0;
}
//关闭日志文件
int ClosePublicLog(){
	INFO("******关闭日志文件******");
	g_PublicLog.ClosePublicLog();
	return 0;
}
#endif
